// Shell服务 - 提供zsh集成功能，包括Sheldon插件管理
// 仅使用safe Rust

#![forbid(unsafe_code)]

use std::sync::{Arc, Mutex};
use std::process::{Command, Stdio};
use std::io::{Result as IoResult, Error as IoError};
use std::os::windows::process::CommandExt;
use std::path::Path;
use log::{info, warn, error};
use dirs;
use shellexpand;

// 导入核心类型
use super::{Capability};
use super::proc_service::{ProcessService, ProcessId};

// Shell服务错误类型
#[derive(Debug, Clone, PartialEq)]
pub enum ShellServiceError {
    InitializationFailed,
    ProcessCreationFailed,
    ProcessNotFound,
    OperationFailed,
    InvalidParameter,
}

// Shell配置
#[derive(Debug, Clone)]
pub struct ShellConfig {
    pub default_shell: String,
    pub shell_path: String,
    pub enable_colors: bool,
    pub history_size: u32,
    pub prompt_style: String,
}

impl Default for ShellConfig {
    fn default() -> Self {
        ShellConfig {
            default_shell: "zsh".to_string(),
            shell_path: "/bin/zsh".to_string(),
            enable_colors: true,
            history_size: 1000,
            prompt_style: "%n@%m:%~$".to_string(),
        }
    }
}

// Shell会话信息
#[derive(Debug, Clone)]
pub struct ShellSession {
    pub session_id: u64,
    pub shell_type: String,
    pub process_id: Option<ProcessId>,
    pub terminal_width: u16,
    pub terminal_height: u16,
    pub started_at: u64,
}

// Sheldon插件信息
#[derive(Debug, Clone)]
pub struct SheldonPlugin {
    pub name: String,
    pub source: String,
    pub kind: String,
    pub tags: Vec<String>,
}

// Shell服务 - 提供zsh集成功能，包括Sheldon插件管理
pub struct ShellService {
    mem_cap: Capability,
    proc_service: Arc<Mutex<ProcessService>>,
    config: ShellConfig,
    sessions: std::sync::RwLock<std::collections::HashMap<u64, ShellSession>>,
    next_session_id: std::sync::atomic::AtomicU64,
    initialized: bool,
    zsh_installed: bool,
    sheldon_installed: bool,
}

impl ShellService {
    // 创建新的Shell服务
    pub fn new(mem_cap: Capability, proc_service: Arc<Mutex<ProcessService>>) -> Result<Self, String> {
        // 检查zsh是否已安装
        let zsh_installed = Self::check_zsh_installation();
        if !zsh_installed {
            warn!("zsh not found, will attempt to use fallback shell");
        }
        
        // 检查Sheldon是否已安装
        let sheldon_installed = Self::check_sheldon_installation();
        if !sheldon_installed {
            info!("Sheldon not found, will attempt to install during startup");
        }
        
        Ok(ShellService {
            mem_cap,
            proc_service,
            config: ShellConfig::default(),
            sessions: std::sync::RwLock::new(std::collections::HashMap::new()),
            next_session_id: std::sync::atomic::AtomicU64::new(1),
            initialized: false,
            zsh_installed,
            sheldon_installed,
        })
    }
    
    // 检查zsh是否已安装
    fn check_zsh_installation() -> bool {
        // 在Windows上，我们可以检查PATH中是否有zsh.exe
        if let Ok(output) = Command::new("where").arg("zsh.exe").output() {
            if output.status.success() {
                info!("zsh found at: {}", String::from_utf8_lossy(&output.stdout));
                return true;
            }
        }
        
        // 也可以检查常见的安装路径
        let common_paths = [
            "C:\\Program Files\\Git\\usr\\bin\\zsh.exe",
            "C:\\msys64\\usr\\bin\\zsh.exe",
            "C:\\cygwin64\\bin\\zsh.exe",
        ];
        
        for path in &common_paths {
            if std::path::Path::new(path).exists() {
                info!("zsh found at: {}", path);
                return true;
            }
        }
        
        false
    }
    
    // 检查Sheldon是否已安装
    fn check_sheldon_installation() -> bool {
        // 在Windows上，检查PATH中是否有sheldon.exe
        if let Ok(output) = Command::new("where").arg("sheldon.exe").output() {
            if output.status.success() {
                info!("Sheldon found at: {}", String::from_utf8_lossy(&output.stdout));
                return true;
            }
        }
        
        // 检查常见的安装路径
        let common_paths = [
            "C:\\Users\\%USERNAME%\\.cargo\\bin\\sheldon.exe",
            "C:\\Program Files\\sheldon\\sheldon.exe",
        ];
        
        for path in &common_paths {
            let expanded_path = shellexpand::tilde(path).to_string();
            if Path::new(&expanded_path).exists() {
                info!("Sheldon found at: {}", expanded_path);
                return true;
            }
        }
        
        false
    }
    
    // 启动Shell服务
    pub fn start(&mut self) -> Result<(), String> {
        if self.initialized {
            return Err("Shell service already started".to_string());
        }
        
        info!("Starting Shell service");
        
        // 如果zsh没有安装，可以尝试安装它
        if !self.zsh_installed {
            if let Err(err) = self.attempt_install_zsh() {
                warn!("Failed to install zsh: {}. Will use fallback shell", err);
            }
        }
        
        // 如果Sheldon没有安装，可以尝试安装它
        if !self.sheldon_installed {
            if let Err(err) = self.attempt_install_sheldon() {
                warn!("Failed to install Sheldon: {}", err);
            } else {
                self.sheldon_installed = true;
            }
        }
        
        // 如果zsh和Sheldon都已安装，确保它们正确集成
        if self.zsh_installed && self.sheldon_installed {
            if let Err(err) = self.setup_sheldon_integration() {
                warn!("Failed to set up Sheldon integration: {}", err);
            }
        }
        
        self.initialized = true;
        info!("Shell service started successfully");
        Ok(())
    }
    
    // 尝试安装zsh（在Windows上通过包管理器）
    fn attempt_install_zsh(&self) -> Result<(), String> {
        // 在Windows上，可以尝试通过winget或choco安装zsh
        if let Ok(output) = Command::new("winget").arg("install").arg("Git.Git").output() {
            if output.status.success() {
                info!("Git (which includes zsh) installed successfully via winget");
                return Ok(());
            }
        }
        
        if let Ok(output) = Command::new("powershell").arg("-Command").arg("choco install -y git").output() {
            if output.status.success() {
                info!("Git (which includes zsh) installed successfully via chocolatey");
                return Ok(());
            }
        }
        
        Err("Failed to install zsh via package managers".to_string())
    }
    
    // 尝试安装Sheldon
    fn attempt_install_sheldon(&self) -> Result<(), String> {
        info!("Attempting to install Sheldon");
        
        // 尝试通过cargo安装Sheldon
        if let Ok(output) = Command::new("powershell").arg("-Command").arg("cargo install sheldon").output() {
            if output.status.success() {
                info!("Sheldon installed successfully via cargo");
                return Ok(());
            }
        }
        
        // 尝试通过chocolatey安装Sheldon
        if let Ok(output) = Command::new("powershell").arg("-Command").arg("choco install -y sheldon").output() {
            if output.status.success() {
                info!("Sheldon installed successfully via chocolatey");
                return Ok(());
            }
        }
        
        // 尝试通过winget安装Sheldon
        if let Ok(output) = Command::new("winget").arg("install").arg("rossmacarthur.sheldon").output() {
            if output.status.success() {
                info!("Sheldon installed successfully via winget");
                return Ok(());
            }
        }
        
        Err("Failed to install Sheldon via available package managers".to_string())
    }
    
    // 设置Sheldon与zsh的集成
    fn setup_sheldon_integration(&self) -> Result<(), String> {
        info!("Setting up Sheldon integration with zsh");
        
        // 获取用户主目录
        let home_dir = match dirs::home_dir() {
            Some(path) => path,
            None => return Err("Failed to get user home directory".to_string()),
        };
        
        // 初始化Sheldon配置
        if let Ok(output) = Command::new("powershell").arg("-Command").arg("sheldon init --shell zsh").output() {
            if !output.status.success() {
                warn!("Sheldon init command failed, but continuing anyway");
            }
        }
        
        // 检查.zshrc文件是否已经包含Sheldon配置
        let zshrc_path = home_dir.join(".zshrc");
        if zshrc_path.exists() {
            if let Ok(content) = std::fs::read_to_string(&zshrc_path) {
                if !content.contains("sheldon source") {
                    // 添加Sheldon到.zshrc
                    if let Err(err) = std::fs::write(
                        &zshrc_path,
                        format!("{}\neval \"$(sheldon source)\"\n", content)
                    ) {
                        return Err(format!("Failed to update .zshrc: {{}}", err));
                    }
                    info!("Added Sheldon integration to .zshrc");
                } else {
                    info!("Sheldon integration already exists in .zshrc");
                }
            }
        } else {
            // 创建.zshrc文件并添加Sheldon配置
            if let Err(err) = std::fs::write(
                &zshrc_path,
                "eval \"$(sheldon source)\"\n"
            ) {
                return Err(format!("Failed to create .zshrc: {{}}", err));
            }
            info!("Created .zshrc with Sheldon integration");
        }
        
        Ok(())
    }
    
    // 创建新的Shell会话
    pub fn create_session(&self, width: u16, height: u16) -> Result<ShellSession, ShellServiceError> {
        if !self.initialized {
            return Err(ShellServiceError::InitializationFailed);
        }
        
        let session_id = self.next_session_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
        
        // 在进程服务中创建一个新进程
        let pid = {
            let mut proc_service = self.proc_service.lock().map_err(|_| ShellServiceError::OperationFailed)?;
            proc_service.create_process(50) // 中等优先级
                .map_err(|_| ShellServiceError::ProcessCreationFailed)?
        };
        
        // 创建Shell会话
        let session = ShellSession {
            session_id,
            shell_type: self.config.default_shell.clone(),
            process_id: Some(pid),
            terminal_width: width,
            terminal_height: height,
            started_at: self.get_current_time_ms(),
        };
        
        // 存储会话信息
        let mut sessions = self.sessions.write().map_err(|_| ShellServiceError::OperationFailed)?;
        sessions.insert(session_id, session.clone());
        
        info!("Created new {} session with ID: {}, PID: {:?}", 
              self.config.default_shell, session_id, pid);
        
        // 启动zsh进程
        self.start_shell_process(pid, width, height)
            .map_err(|_| ShellServiceError::ProcessCreationFailed)?;
        
        Ok(session)
    }
    
    // 启动shell进程
    fn start_shell_process(&self, pid: ProcessId, width: u16, height: u16) -> Result<(), IoError> {
        // 获取zsh的实际路径
        let zsh_path = self.find_zsh_path();
        
        // 设置环境变量
        let mut cmd = Command::new(zsh_path);
        
        // 设置终端大小环境变量
        cmd.env("COLUMNS", width.to_string())
           .env("LINES", height.to_string())
           .env("TERM", "xterm-256color")
           .env("PROMPT", self.config.prompt_style.clone());
        
        // 设置标准输入、输出和错误
        cmd.stdin(Stdio::piped())
           .stdout(Stdio::piped())
           .stderr(Stdio::piped());
        
        // 启动进程
        let child = cmd.spawn()?;
        
        // 记录进程信息
        info!("Started {} process with system PID: {}", self.config.default_shell, child.id());
        
        Ok(())
    }
    
    // 查找zsh路径
    fn find_zsh_path(&self) -> String {
        // 在Windows上，我们需要找到实际的zsh可执行文件路径
        if let Ok(output) = Command::new("where").arg("zsh.exe").output() {
            if output.status.success() {
                return String::from_utf8_lossy(&output.stdout)
                    .trim()
                    .to_string();
            }
        }
        
        // 检查常见安装路径
        let common_paths = [
            "C:\\Program Files\\Git\\usr\\bin\\zsh.exe",
            "C:\\msys64\\usr\\bin\\zsh.exe",
            "C:\\cygwin64\\bin\\zsh.exe",
        ];
        
        for path in &common_paths {
            if std::path::Path::new(path).exists() {
                return path.to_string();
            }
        }
        
        // 如果找不到，回退到cmd.exe
        "cmd.exe".to_string()
    }
    
    // 查找Sheldon配置文件路径
    fn find_sheldon_config_path(&self) -> Result<String, String> {
        let home_dir = match dirs::home_dir() {
            Some(path) => path,
            None => return Err("Failed to get user home directory".to_string()),
        };
        
        let config_paths = [
            home_dir.join(".sheldon").join("plugins.toml"),
            home_dir.join(".config").join("sheldon").join("plugins.toml"),
        ];
        
        for path in &config_paths {
            if path.exists() {
                return Ok(path.to_string_lossy().to_string());
            }
        }
        
        // 如果都不存在，返回默认路径
        Ok(config_paths[0].to_string_lossy().to_string())
    }
    
    // 安装Sheldon插件
    pub fn install_sheldon_plugin(&self, name: &str, source: &str, kind: &str) -> Result<(), String> {
        if !self.initialized || !self.sheldon_installed {
            return Err("Shell service not initialized or Sheldon not installed".to_string());
        }
        
        info!("Installing Sheldon plugin: {} from {}", name, source);
        
        // 尝试通过sheldon add命令安装插件
        let command = format!("sheldon add {} --{} {}", name, kind, source);
        if let Ok(output) = Command::new("powershell").arg("-Command").arg(&command).output() {
            if output.status.success() {
                info!("Successfully installed Sheldon plugin: {}", name);
                return Ok(());
            } else {
                let error_output = String::from_utf8_lossy(&output.stderr);
                return Err(format!("Failed to install plugin: {}", error_output));
            }
        }
        
        Err("Failed to execute Sheldon command".to_string())
    }
    
    // 列出已安装的Sheldon插件
    pub fn list_sheldon_plugins(&self) -> Result<Vec<SheldonPlugin>, String> {
        if !self.initialized || !self.sheldon_installed {
            return Err("Shell service not initialized or Sheldon not installed".to_string());
        }
        
        info!("Listing Sheldon plugins");
        
        // 解析plugins.toml文件
        let config_path = self.find_sheldon_config_path()?;
        if !Path::new(&config_path).exists() {
            return Ok(Vec::new());
        }
        
        let content = std::fs::read_to_string(&config_path)
            .map_err(|err| format!("Failed to read config file: {}", err))?;
        
        // 简化实现：实际应该使用toml解析库
        let mut plugins = Vec::new();
        
        // 这里只是模拟解析，实际项目中应该使用toml库
        info!("Plugins found in config file: {}", config_path);
        
        Ok(plugins)
    }
    
    // 删除Sheldon插件
    pub fn remove_sheldon_plugin(&self, name: &str) -> Result<(), String> {
        if !self.initialized || !self.sheldon_installed {
            return Err("Shell service not initialized or Sheldon not installed".to_string());
        }
        
        info!("Removing Sheldon plugin: {}", name);
        
        // 尝试通过sheldon remove命令删除插件
        let command = format!("sheldon remove {}", name);
        if let Ok(output) = Command::new("powershell").arg("-Command").arg(&command).output() {
            if output.status.success() {
                info!("Successfully removed Sheldon plugin: {}", name);
                return Ok(());
            } else {
                let error_output = String::from_utf8_lossy(&output.stderr);
                return Err(format!("Failed to remove plugin: {}", error_output));
            }
        }
        
        Err("Failed to execute Sheldon command".to_string())
    }
    
    // 结束Shell会话
    pub fn terminate_session(&self, session_id: u64) -> Result<bool, ShellServiceError> {
        if !self.initialized {
            return Err(ShellServiceError::InitializationFailed);
        }
        
        // 查找会话
        let mut sessions = self.sessions.write().map_err(|_| ShellServiceError::OperationFailed)?;
        let session = match sessions.get(&session_id) {
            Some(session) => session.clone(),
            None => return Err(ShellServiceError::ProcessNotFound),
        };
        
        // 结束进程
        if let Some(pid) = session.process_id {
            let mut proc_service = self.proc_service.lock().map_err(|_| ShellServiceError::OperationFailed)?;
            proc_service.destroy_process(pid)
                .map_err(|_| ShellServiceError::OperationFailed)?;
        }
        
        // 移除会话
        sessions.remove(&session_id);
        
        info!("Terminated {} session with ID: {}", session.shell_type, session_id);
        Ok(true)
    }
    
    // 发送命令到Shell会话
    pub fn send_command(&self, session_id: u64, command: &str) -> Result<bool, ShellServiceError> {
        if !self.initialized {
            return Err(ShellServiceError::InitializationFailed);
        }
        
        // 查找会话
        let sessions = self.sessions.read().map_err(|_| ShellServiceError::OperationFailed)?;
        if !sessions.contains_key(&session_id) {
            return Err(ShellServiceError::ProcessNotFound);
        }
        
        // 这里应该实现向shell进程发送命令的逻辑
        // 实际实现需要使用进程间通信
        info!("Sending command to session {}: {}", session_id, command);
        
        // 简化实现：假设命令已发送
        Ok(true)
    }
    
    // 获取所有活动会话
    pub fn list_sessions(&self) -> Result<Vec<ShellSession>, ShellServiceError> {
        if !self.initialized {
            return Err(ShellServiceError::InitializationFailed);
        }
        
        let sessions = self.sessions.read().map_err(|_| ShellServiceError::OperationFailed)?;
        Ok(sessions.values().cloned().collect())
    }
    
    // 获取当前时间（毫秒）
    fn get_current_time_ms(&self) -> u64 {
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_millis() as u64
    }
}